package controller

import (
	"awesomeProject/lib"
	"encoding/json"
	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
	"github.com/mitchellh/mapstructure"
	"log"
	"strconv"
)

var (
	upgrader = websocket.Upgrader{
		ReadBufferSize:  1024,
		WriteBufferSize: 1024,
	}

	clients = make(map[int64]*websocket.Conn)
)

func HandleChatMsg(data *map[string]interface{}) (lib.Message, error) {
	var message lib.Message
	if err := mapstructure.Decode(*data, &message); err != nil {
		log.Println("read json fail in handleChatMsg", err)
		return message, err
	}
	log.Println(message)
	return message, nil
}

func HandleFriendMsg(data *map[string]interface{}) (lib.CheckFriendMsg, error) {
	log.Println(data)
	var message lib.CheckFriendMsg
	if err := mapstructure.Decode(*data, &message); err != nil {
		log.Println("handle json fail in handle friend msg")
		return message, err
	}
	log.Println(message)
	return message, nil
}

func WsHandler(c *gin.Context) {
	// 建立连接
	idRaw, err := strconv.Atoi(c.Query("id"))
	if err != nil {
		log.Println("id conv fail in ws")
		return
	}
	id := int64(idRaw)
	token := c.Query("token")
	// 检查当前的操作是否由合法用户作出
	ok, err := AuthId(id, token)
	if !ok || err != nil {
		c.JSON(500, lib.UpgradeResp{
			StatusCode: 0,
			StatusMsg:  "auth fail",
		})
	}
	// 升级为websocket协议
	conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
	if err != nil {
		log.Println("upgrade protocol fail in wshandler")
		c.JSON(400, lib.UpgradeResp{
			StatusCode: 0,
			StatusMsg:  "upgrade protocol fail in wshandler",
		})
		return
	}
	clients[id] = conn // 添加到当前在线用户列表

	// 拉取全部未读消息
	ucMessage, cnt, err := PullUncheckedMsg(id)
	if err != nil {
		log.Println("无未读信息或者数据库错误")
	} else {
		resp := lib.PullMsgQueue{
			SumNum:     cnt,
			Type:       "pull_chat",
			UcMessages: *ucMessage,
		}
		if err := conn.WriteJSON(resp); err != nil {
			log.Println("send unchecked message fail in ws")
		}
	}

	// 拉去全部未读好友请求
	unReq, cnt := PullFrdReq(id)
	msgs := lib.PullFrdReqQueue{
		SumNum:   cnt,
		Type:     "pull_friend_req",
		ReqQueue: unReq,
	}
	if err := conn.WriteJSON(msgs); err != nil {
		log.Println("send friend req queue fail in ws")
	}
	for {
		_, message, err := conn.ReadMessage() // message为[]byte
		if err != nil {
			if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
				log.Printf("error: %v", err)
			}
			log.Println("read message fail in ws", err)
			delete(clients, id)
			break
		}
		var data map[string]interface{}
		if err := json.Unmarshal(message, &data); err != nil {
			log.Println("unmarshal json fail in ws", err)
			continue
		}
		if data["type"].(string) == "chat" {
			content, err := HandleChatMsg(&data)
			err = Chat(&content)
			if err != nil {
				log.Println("send chat message fail in ws", err)
				continue
			}
		} else if data["type"].(string) == "add_friend_fail_or_success" {
			if err := BuildFriendMsg(&data); err != nil {
				log.Println("handle add friend fail in ws", err)
				continue
			}
		} else {
			continue
		}

	}
}
